package net.guerlab.qcloud.im.sdk.autoconfigure;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import net.guerlab.qcloud.im.sdk.ImClient;
import net.guerlab.qcloud.im.sdk.client.OkHttpImClient;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

/**
 * Im自动配置
 */
@Slf4j
@Configuration
@EnableConfigurationProperties(IMProperties.class)
public class IMAutoconfigure {

    private OkHttpClient okHttpClient;

    /**
     * 创建http请求客户端
     *
     * @return http请求客户端
     */
    private static OkHttpClient createHttpClient() {
        return new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS).readTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS).sslSocketFactory(createSSLSocketFactory(), new TrustAllManager())
                .hostnameVerifier((hostname, session) -> true).build();
    }

    private static SSLSocketFactory createSSLSocketFactory() {
        SSLSocketFactory sSLSocketFactory = null;

        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, new TrustManager[] { new TrustAllManager() }, new SecureRandom());
            sSLSocketFactory = sc.getSocketFactory();
        } catch (Exception e) {
            log.debug(e.getMessage(), e);
        }

        return sSLSocketFactory;
    }

    @Autowired(required = false)
    public void setOkHttpClient(OkHttpClient okHttpClient) {
        this.okHttpClient = okHttpClient;
    }

    /**
     * 设置控制器映射
     *
     * @param properties
     *         Im配置
     */
    @Bean
    public ImClient imClient(IMProperties properties) {
        Long sdkAppId = properties.getSdkAppId();
        String key = properties.getKey();
        String identifier = properties.getIdentifier();

        Assert.notNull(sdkAppId, "sdkAppId cannot be null");
        Assert.notNull(key, "key cannot be null");
        Assert.notNull(identifier, "identifier cannot be null");

        return new OkHttpImClient(sdkAppId, key, identifier, client(), new ObjectMapper());
    }

    private OkHttpClient client() {
        if (okHttpClient != null) {
            return okHttpClient;
        }

        return createHttpClient();
    }

    private static class TrustAllManager implements X509TrustManager {

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) {
            /*
             * ignore
             */
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) {
            /*
             * ignore
             */
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[] {};
        }
    }
}
